#
# skeleton.py - An example showing the basic structure of a complex setup with
# multiple scenes and various other features.
#

from mididings import *
from mididings.extra import *
from mididings.extra.osc import SendOSC
import time

# some classes are defined in separate modules because they depend on
# additional Python packages to be installed. uncomment these imports if you
# need them
#from mididings.extra.osc import OSCInterface
#from mididings.extra.inotify import AutoRestart

mixerPort = 7587
sooperLooperPort = 9951
config(
    # uncomment this to use the JACK MIDI backend instead of ALSA sequencer
    #backend='jack',

    # you can assign names to input/output ports...
    out_ports=['hydrogen', 'fluidsynth', 'sooperlooper', 'yoshimi'],
    # ...or just change the number of ports available
    #in_ports=2,

    # when using a patchbay like QjackCtl, a small delay allows ports to be
    # connected before any MIDI events are sent
    #start_delay=0.5,
)

hook(
    # some functions (like scene switching) can be controlled via OSC.
    # this is needed for the livedings GUI, for example.
    # by default, UDP port 56418 is used to control mididings, and mididings
    # will send notification to port 56419.
    #OSCInterface(),

    # uncomment this if you want mididings to restore the previously active
    # scene when it is restarted
    #MemorizeScene('scene.txt'),

    # mididings can automatically watch this script (and modules it imports)
    # for changes, and restart itself automatically
    #AutoRestart(),
)


# in this example, we use the control to switch scenes in response to program
# change events
control = Filter(PROGRAM) >> SceneSwitch()

# use the pre and post patches to print all incoming and outgoing events.
# pre also filters out program changes, as these are already handled by the
# control patch and probably meaningless for individual scenes
pre = Print('input', portnames='in') #>> ~Filter(PROGRAM)
post = Print('output', portnames='out')


# define some sounds/outputs.
# by using OutputTemplate() instead of Output(), we allow additional
# parameters (like volume) to be specified later, when these sounds are used
# in patches.
# synth1 = Output('fluidsynth', 1)              
#synth2 = Output('fluidsynth', 2)              
#synth2  = OutputTemplate('aaa', 2, None) 

synth1  = OutputTemplate('fluidsynth', 1, None) 
drum10  = OutputTemplate('hydrogen', 10, None) 
looper1  = OutputTemplate('sooperlooper', 1, None) 
yoshimi1 = OutputTemplate('yoshimi', 1, None)

#eggs1 = OutputTemplate('fluidsynth', 1, 23)   # channel 1, program 23 on port 'eggs'
#eggs2 = OutputTemplate('fluidsynth', 1, 42)   # channel 1, program 42 on port 'eggs'


def f(self):
 	print "ala"
	a = 0;
	while a < 13:
		a = a + 1
		#print a	
		# Pitchbend(a);
		#NoteOn('c3', 80)				
		#time.sleep(0.1);
		#NoteOn('c4', 80)		
		
## now define some patches using the sounds defined above
scenePatch_1 = [ ChannelSplit({1: Filter(NOTE),
			      10: Filter(PROGRAM) })
					>> synth1 (100),
		 ChannelSplit({2: Filter(NOTE),
                              10: Filter(PROGRAM) })
                                        >> yoshimi1 (100),
		 ChannelFilter(10) >> Filter(NOTEON) 
					>> drum10(100),

		 ChannelFilter([9]) >> Filter(PROGRAM) >> ProgramSplit ({
					101: SendOSC(sooperLooperPort, '/set', 'selected_loop_num', 0),
					102: SendOSC(sooperLooperPort, '/set', 'selected_loop_num', 1),
					103: SendOSC(sooperLooperPort, '/set', 'selected_loop_num', 2),
					104: SendOSC(sooperLooperPort, '/set', 'selected_loop_num', 3),
		 }) >> Call (f),	
		
		 Filter(CTRL) >> ChannelFilter([1,2,7])
		              >> looper1(90) 
                              >> CtrlSplit(
		{
		
		5: CtrlMap (5, 20) >> Channel(1),
                6: CtrlMap (6, 21) >> Channel(1),
                4: CtrlMap (4, 22) >> Channel(1),
                8: CtrlMap (8, 23) >> Channel(1),

		20: Channel(1),
		21: Channel(1),
		22: Channel(1),
		23: Channel(1),		
		100: SendOSC(mixerPort, '/strip/git/Gain/Gain%20(dB)', lambda ev: ev.value / 127.0),
		101: SendOSC(mixerPort, '/strip/keys/Gain/Gain%20(dB)', lambda ev: ev.value / 127.0),
		102: SendOSC(mixerPort, '/strip/drum/Gain/Gain%20(dB)', lambda ev: ev.value / 127.0),
		103: SendOSC(mixerPort, '/strip/all/Gain/Gain%20(dB)', lambda ev: ev.value / 127.0),}),
		]

#scenePatch_2 = [ ChannelSplit({1: Filter(NOTE),
#			      10: Filter(PROGRAM) })
#					>> KeySplit('c3', synth1, synth2),
#		 ChannelFilter(10) >> Filter(NOTE) 
#					>> drum10(100),
#		 Filter(CTRL) >> ChannelFilter([1,7]) 
#					>> looper1(90),		
#		]


# finally, assign scene names and program numbers to these patches...
scenes = {
    1:  Scene("Scene1", scenePatch_1),
#    2:  Scene("Scene2", scenePatch_2),
   # 2:  SceneGroup("Dummy SceneGroup", [
   #         Scene("Subscene A", dummy_2a),
   #         Scene("Subscene B", dummy_2b),
   #     ]),
    # ...
}


# ...and start the whole thing...
run(
    control=control,
    pre=pre,
    post=post,
    scenes=scenes,
)
